package com.thoughtservice.jspdoc.export.argouml;

/*
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code is "JSP Documentation Generator Project".
 *
 */

import java.util.*;
import java.io.*;

import com.thoughtservice.jspdoc.*;

/**
 * Creates XMI documents of ArgoUML Project files
 *
 * @author Jochen Luell (jochen@luell.com)
 */
public class XmiDocument {

  private StringBuffer xmiOut;

  private final static String XMI_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" +
       "<XMI xmi.version=\"1.0\">\r\n" +
       "  <XMI.header>\r\n" +
       "    <XMI.documentation>\r\n" +
       "      <XMI.exporter>Novosoft UML Library</XMI.exporter>\r\n" +
       "      <XMI.exporterVersion>0.4.19</XMI.exporterVersion>\r\n" +
       "    </XMI.documentation>\r\n" +
       "    <XMI.metamodel xmi.name=\"UML\" xmi.version=\"1.3\"/>\r\n" +
       "  </XMI.header>\r\n" +
       "  <XMI.content>\r\n" +
       "    <Model_Management.Model xmi.id=\"xmi.1\" xmi.uuid=\"10-48--7-111-ad483:f0a47428ae:-8000\">\r\n" +
       "      <Foundation.Core.ModelElement.name>untitledModel</Foundation.Core.ModelElement.name>\r\n" +
       "      <Foundation.Core.ModelElement.isSpecification xmi.value=\"false\"/>\r\n" +
       "      <Foundation.Core.GeneralizableElement.isRoot xmi.value=\"false\"/>\r\n" +
       "      <Foundation.Core.GeneralizableElement.isLeaf xmi.value=\"false\"/>\r\n" +
       "      <Foundation.Core.GeneralizableElement.isAbstract xmi.value=\"false\"/>\r\n" +
       "      <Foundation.Core.Namespace.ownedElement>\r\n";
  
   private final static String XMI_FOOTER = "      </Foundation.Core.Namespace.ownedElement>\r\n" +
       "    </Model_Management.Model>\r\n" +
       "  </XMI.content>\r\n" +
       "</XMI>\r\n";


   private final static String XMI_CLASS_START = "<Foundation.Core.Class xmi.id=\"CLASS-NAME\" xmi.uuid=\"CLASS-HASH\">\r\n" +
       "          <Foundation.Core.ModelElement.name>JSP-NAME</Foundation.Core.ModelElement.name>\r\n" +
       "          <Foundation.Core.ModelElement.isSpecification xmi.value=\"false\"/>\r\n" +
       "          <Foundation.Core.GeneralizableElement.isRoot xmi.value=\"false\"/>\r\n" +
       "          <Foundation.Core.GeneralizableElement.isLeaf xmi.value=\"false\"/>\r\n" +
       "          <Foundation.Core.GeneralizableElement.isAbstract xmi.value=\"false\"/>\r\n" +
       "          <Foundation.Core.Class.isActive xmi.value=\"false\"/>\r\n" +
       "          <Foundation.Core.ModelElement.namespace>\r\n" +
       "            <Foundation.Core.Namespace xmi.idref=\"xmi.1\"/>\r\n" +
       "          </Foundation.Core.ModelElement.namespace>\r\n";

   private final static String XMI_CLASS_END =  "          <Foundation.Core.ModelElement.taggedValue>\r\n" +
       "            <Foundation.Extension_Mechanisms.TaggedValue xmi.id=\"CLASS-DOCNAME\">\r\n" +
       "              <Foundation.Extension_Mechanisms.TaggedValue.tag>documentation</Foundation.Extension_Mechanisms.TaggedValue.tag>\r\n" +
       "              <Foundation.Extension_Mechanisms.TaggedValue.value>JSP-DOC</Foundation.Extension_Mechanisms.TaggedValue.value>\r\n" +
       "              <Foundation.Extension_Mechanisms.TaggedValue.modelElement>\r\n" +
       "                <Foundation.Core.ModelElement xmi.idref=\"CLASS-NAME\"/>\r\n" +
       "              </Foundation.Extension_Mechanisms.TaggedValue.modelElement>\r\n" +
       "            </Foundation.Extension_Mechanisms.TaggedValue>\r\n" +
       "          </Foundation.Core.ModelElement.taggedValue>\r\n" +
       "        </Foundation.Core.Class>\r\n";
       
  public static final String XMI_CLASS_DEPENDENCY = "           <Foundation.Core.ModelElement.DEP-TYPE>\r\n" +
       "              <Foundation.Core.Dependency xmi.idref=\"DEP-DEF\"/>\r\n" +
       "           </Foundation.Core.ModelElement.DEP-TYPE>\r\n";
       
  public static final String XMI_DEPENDENCY = "        <Foundation.Core.Dependency xmi.id=\"DEP-NAME\" xmi.uuid=\"DEP-HASH\">\r\n" +
       "          <Foundation.Core.ModelElement.name>DEP-LABEL</Foundation.Core.ModelElement.name>\r\n" +
       "          <Foundation.Core.ModelElement.isSpecification xmi.value=\"false\"/>\r\n" +
       "          <Foundation.Core.ModelElement.namespace>\r\n" +
       "            <Foundation.Core.Namespace xmi.idref=\"xmi.1\"/>\r\n" +
       "          </Foundation.Core.ModelElement.namespace>\r\n" +
       "          <Foundation.Core.Dependency.client>\r\n" +
       "            <Foundation.Core.ModelElement xmi.idref=\"DEP-SOURCE\"/>\r\n" +
       "          </Foundation.Core.Dependency.client>\r\n" +
       "          <Foundation.Core.Dependency.supplier>\r\n" +
       "            <Foundation.Core.ModelElement xmi.idref=\"DEP-DEST\"/>\r\n" +
       "          </Foundation.Core.Dependency.supplier>\r\n" +
       "        </Foundation.Core.Dependency>\r\n";

public static final String XMI_EMPTY_DEPENDENCY = "        <Foundation.Core.Dependency xmi.id=\"DEP-NAME\" xmi.uuid=\"DEP-HASH\">\r\n" +
       "          <Foundation.Core.ModelElement.isSpecification xmi.value=\"false\"/>\r\n" +
       "          <Foundation.Core.ModelElement.namespace>\r\n" +
       "            <Foundation.Core.Namespace xmi.idref=\"xmi.1\"/>\r\n" +
       "          </Foundation.Core.ModelElement.namespace>\r\n" +
       "        </Foundation.Core.Dependency>\r\n";


  /**
   * Class constructor
   */
  public XmiDocument() {
          xmiOut = new StringBuffer();
  }

  /**
   * Creates the XMI header
   */
  public void createHeader() {
	  xmiOut.append(XMI_HEADER);
  }

  /**
   * Creates the XMI footer
   */
  public void createFooter() {
	  xmiOut.append(XMI_FOOTER);
  }

  /**
   * Adds an XMI Class
   *
   * @param e ca.yourdecor.jspdoc.export.argouml.GroupElement Element definition
   * @param pages ca.yourdecor.jspdoc.JSPFileList List of JSP pages
   * @see com.thoughtservice.jspdoc.export.argouml.GroupElement
   */
  public void addClass(GroupElement e, JSPFileList pages) {
	  try {
	    String out = XMI_CLASS_START;
	    RE re;

	    re = new RE("CLASS-NAME");
	    out = re.subst(out, e.getXmiName());

	    re = new RE("CLASS-HASH");
	    out = re.subst(out, "" + e.getJspName().hashCode() + "-" + e.getLinkTypeTo());
	    
	    re = new RE("JSP-NAME");
	    out = re.subst(out, e.getJspName());

	    xmiOut.append(out);

            // Now add the dependencies
	    String rootPath = pages.getRootDir().getAbsolutePath();

	    JSPPage p = e.getJspPage();

            if(p.isPage()) {
               Iterator linksTo = p.getConnections(e.getLinkTypeTo());

	       while(linksTo.hasNext()) {
	           File f = (File) linksTo.next();
		   
		   if(! f.exists()) {
		      continue;
		   }

		   String destName = f.getAbsolutePath().substring(rootPath.length());
		   destName = destName.replace('\\', '/');

		   out = XMI_CLASS_DEPENDENCY;
                   re = new RE("DEP-DEF");
	           out = re.subst(out, e.getJspName().hashCode() + "-" +
		          destName.hashCode() + "-" + e.getLinkTypeTo());

		   re = new RE("DEP-TYPE");
		   out = re.subst(out, "clientDependency");

		   xmiOut.append(out);
               }

               if(e.getLinkTypeFrom() != -1) {
	           Iterator linksFrom = p.getConnections(e.getLinkTypeFrom());

	           while(linksFrom.hasNext()) {
	               File f = (File) linksFrom.next();
		   
		       if(! f.exists()) {
		          continue;
		       }

		       String sourceName = f.getAbsolutePath().substring(rootPath.length());
		       sourceName = sourceName.replace('\\', '/');

                       out = XMI_CLASS_DEPENDENCY;
                       re = new RE("DEP-DEF");
	               out = re.subst(out, sourceName.hashCode() + "-" + e.getJspName().hashCode() +
		                  "-" + e.getLinkTypeTo());

		       re = new RE("DEP-TYPE");
		       out = re.subst(out, "supplierDependency");

		       xmiOut.append(out);
                   }
             }


            }

            out = XMI_CLASS_END;

            re = new RE("JSP-NAME");
	    out = re.subst(out, e.getJspName());

	    re = new RE("CLASS-DOCNAME");
	    out = re.subst(out, e.getXmiName() + "doc");
	    
	    re = new RE("CLASS-NAME");
	    out = re.subst(out, e.getXmiName());

	    re = new RE("JSP-DOC");
	    out = re.subst(out, e.getDescription() != null ? e.getDescription() : "");

            xmiOut.append(out);
	  }
	  catch(Exception ex) {
		  ex.printStackTrace();
          }
  }

  /**
   * Adds an XMI Element dependencies
   *
   * @param source ca.yourdecor.jspdoc.export.argouml.GroupElement Source element definition
   * @param dest ca.yourdecor.jspdoc.export.argouml.GroupElement Destination element definition
   * @see com.thoughtservice.jspdoc.export.argouml.GroupElement
   */
  public void addDependency(GroupElement source, GroupElement dest) {
	  try {
	    String out = XMI_DEPENDENCY;


	    RE re;

	    re = new RE("DEP-NAME");
	    out = re.subst(out, source.getJspName().hashCode() + "-" +
	         dest.getJspName().hashCode() + "-" + source.getLinkTypeTo());

            re = new RE("DEP-LABEL");
	    out = re.subst(out, source.getJspName() + " -> " +
	         dest.getJspName());

	    re = new RE("DEP-SOURCE");
	    out = re.subst(out, source.getXmiName());

            re = new RE("DEP-DEST");
	    out = re.subst(out, dest.getXmiName());
	    
	    re = new RE("DEP-HASH");
	    out = re.subst(out, source.getJspName().hashCode() + "-" +
	                dest.getJspName().hashCode() + "-" + source.getLinkTypeTo());


            xmiOut.append(out);
	  }
	  catch(Exception e) {
		  e.printStackTrace();
          }
  }

  /**
   * Adds an empty XMI Element dependencies
   *
   * @param source  Name of source jsp page
   * @param source  Name of destination jsp page
   * @param linkType  Type of link
   */
  public void addEmptyDependency(String source, String dest, int linkType) {
	  try {
	    String out = XMI_EMPTY_DEPENDENCY;


	    RE re;

	    re = new RE("DEP-NAME");
	    out = re.subst(out, source.hashCode() + "-" +
	         dest.hashCode() + "-" + linkType);

	    re = new RE("DEP-HASH");
	    out = re.subst(out, source.hashCode() + "-" +
	                dest.hashCode() + "-" + linkType);


            xmiOut.append(out);
	  }
	  catch(Exception e) {
		  e.printStackTrace();
          }
  }

  /**
   * Returns the XMI document
   *
   * @return java.lang.String The PGML document
   */
  public String getDocument() {
      return xmiOut.toString();
  }

}
